package core;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import rm.Node;
import rm.ProcLauncher;
import rm.RMProcess;
import interfaces.*;
import proxy.*;

public class Launcher implements ILauncher, IRemoteNode {

	// Procurador do lançador
	private LauncherProxy launcherProxy;

	// Cria uma lista para armazenar o canal de conexão dos prog. lançados
	private LinkedHashMap<String, String> nodesChannelList;

	// Cria uma lista de nodes. Os que serão lidos do arquivo
	private LinkedList<Node> nodesList;
	
	// Cria uma lista para armazenar os nodes lançados
	private LinkedHashMap<String, Node> nodesLaunchList;

	// identificação do node
	private String ID_NODE;
	
	// Node físico
	private String HOSTNAME;
	
	// Porta de conexão
	private int SSH_PORT;
	
	// Usuario para conexao
	private String USER;
	
	// Senha para conexao
	private String PASSWORD;
	
	// Aplicação que sera lancada pelo lancador
	private String PROG;
	
	// Identificação do gerente do node que esta sendo lancado
	private String IDBOSS;
	
	// Descrição do canal de comunicação com o lancador 
	private String launcherChannelDesc;
	
	public Launcher(LauncherProxy launcherProxy, String launcherChannelDesc) {
		try {
			this.launcherProxy = launcherProxy;
			this.launcherChannelDesc = launcherChannelDesc;

			// Instancia uma lista de nodes, lida do arquivo
			this.nodesList = new LinkedList<Node>();

			// Cria uma lista para armazenar o canal de conexão dos prog. lançados
			this.nodesLaunchList = new LinkedHashMap<String, Node>();
			
			// Cria uma lista para armazenar o canal de conexão dos prog. lançados
			this.nodesChannelList = new LinkedHashMap<String, String>();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void Initialize(File nodeFile) throws IOException {
		// TODO Auto-generated method stub
		char[] buffer = new char[(int) nodeFile.length()];
		String[] nodes;
		FileReader reader = new FileReader(nodeFile);

		reader.read(buffer);
		nodes = new String(buffer).split("\n");
		for (String node : nodes) {
			String[] nodesInfo = node.split(":");
			this.ID_NODE = nodesInfo[0];
			this.HOSTNAME = nodesInfo[1];
			this.SSH_PORT = Integer.parseInt(nodesInfo[2]);
			this.USER = nodesInfo[3];
			this.PASSWORD = nodesInfo[4];
			this.PROG = nodesInfo[5];
			this.IDBOSS = nodesInfo[6];
			this.nodesList.add(new Node(ID_NODE, HOSTNAME, SSH_PORT, USER, PASSWORD, PROG, IDBOSS));
			
			/////////////////////////////////////////////////////////////////////////
			//System.out.println("Launcher => ");
			//System.out.println("\t Lendo Arquivo");
			//System.out.println("\t\t ID_NODE: " + ID_NODE);
			//System.out.println("\t\t HOSTNAME: " + HOSTNAME);
			//System.out.println("\t\t SSH_PORT: " + SSH_PORT);
			//System.out.println("\t\t USER: " + USER);
			//System.out.println("\t\t PASSWORD: " + PASSWORD);
			//System.out.println("\t\t PROG: " + PROG);
			//System.out.println("\t\t IDBOSS: " + IDBOSS + "\n");
			/////////////////////////////////////////////////////////////////////////
		}
	}

	@Override
	public void launchNodes() throws IOException, InterruptedException {
		// TODO Auto-generated method stub
		
		/////////////////////////////////////////////////////////////////////////
		//System.out.println("Launcher => ");
		//System.out.println("\t Irei Lancar \n");
		/////////////////////////////////////////////////////////////////////////

		for (int i = 0; i < nodesList.size(); i++) {
			Node nodeQ = nodesList.get(i);
			RMProcess aux = new RMProcess(Config.JAVA_BIN,
					Config.JAVA_ENCODING + Config.CLASSPATH_JAVA
							+ Config.TOOLS_SSH + Config.JAVA_CLASS
							+ nodeQ.getProg() + " " + nodeQ.getId() + " " + nodeQ.getHostName() + " " 
							+ getChannelDesc());
			ProcLauncher.launchProcess(nodeQ, aux);
			this.nodesLaunchList.put(nodeQ.getId(), nodeQ);
			Thread.sleep(1000);
		}
	}

	@Override
	public void nodeStarted(String nodeId, String nodeChannelDescription) {
		// TODO Auto-generated method stub
		try {
			/////////////////////////////////////////////////////////////////////////
			//System.out.println("Launcher => ");
			//System.out.println("\t Recebi Msg. NODE_STARTED");
			//System.out.println("\t\t NodeID: " + nodeId);
			//System.out.println("\t\t ChannelDesc: " + nodeChannelDescription);
			/////////////////////////////////////////////////////////////////////////
			this.nodesChannelList.put(nodeId, nodeChannelDescription);
			Node n = this.nodesLaunchList.get(nodeId);
			String boss = n.getIdBoss();
			String bossChannelDesc = this.nodesChannelList.get(boss);

			if (bossChannelDesc == null) {
				System.out.println("Launcher => ");
				System.out.println("\t ERRO NAO ACHEI O CANAL DO BOSS DO : " + nodeId);
				System.exit(0);
			} else {
				this.launcherProxy.sendNewWorker(nodeId, nodeChannelDescription, bossChannelDesc);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public String getBossContact() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ICommunicator getChannel() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setChannelDesc(String channelDesc) {
		// TODO Auto-generated method stub
		this.launcherChannelDesc = channelDesc;
	}

	@Override
	public String getChannelDesc() {
		// TODO Auto-generated method stub
		return this.launcherChannelDesc;
	}


	@Override
	public void setBossContact(String workerId) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setChannel(ICommunicator channel) {
		// TODO Auto-generated method stub
		
	}
}
